package com.editso.haier.result;

import com.editso.haier.util.Promise;
import lombok.Data;

import java.util.Date;

@Data
public class Result {

    private final ResultCode status;
    private final String message;
    private final Object data;
    private final Date date;

    public Result(ResultCode status, String message, Object data) {
        this.status = status;
        this.message = message == null ? status.getMessage() : message;
        this.data = data;
        this.date = new Date();
    }

    public static Result result(Object data, String message, ResultCode status){
        return new Result(status, message, data);
    }

    public static Result result(String message, ResultCode status){
        return result(null, message, status);
    }

    public static Result result(ResultCode code){
        return result(null, code);
    }

    public static Result success(Object data, String message){
        return result(data, message, ResultCode.SUCCESS);
    }

    public static Result success(Object data){
        return success(data, null);
    }

    public static Result success(){
        return success(null);
    }

    public static Result failure(Object data, String message){
        return result(data, message, ResultCode.FAILURE);
    }

    public static Result failure(Object date){
        return failure(date, null);
    }

    public static Result failure(String message){
        return failure(null, message);
    }

    public static Result failure(){
        return failure(null);
    }
    
    public static <T> Result promise(Promise.VoidFunctional<Promise.Callback<Result, T>> functional,
                                     Promise.VoidFunctional<Promise<T, Result>> promiseVoidFunctional){
        Promise<T, Result> promise = new Promise<>(functional, accept -> Result.success(), err -> Result.failure());
        try {
            promiseVoidFunctional.apply(promise);
            return promise.get();
        }catch (Exception e){
            e.printStackTrace();
            return promise.get();
        }
    }

    public static <T> Result promise(Promise.VoidFunctional<Promise.Callback<Result, T>> functional){
        return promise(functional, tResultPromise -> {});
    }
}
